#ifndef __TIMEPOINT_H
#define __TIMEPOINT_H

/**
 * @brief 每一时刻对应一个指标计数器
 *
 */
typedef struct {
        struct timeval t;
        uint64_t count;
} timepoint1_t;

typedef struct {
        char name[MAX_NAME_LEN];
        timepoint1_t p1;
        timepoint1_t p2;
        int64_t interval;
        uint64_t speed;
} timerange1_t;

static inline int timerange1_init(timerange1_t *range, const char *name, int64_t interval) {
        strcpy(range->name, name);
        range->interval = interval;
        range->speed = 0;

        _gettimeofday(&range->p1.t, NULL);
        range->p1.count = 0;

        _gettimeofday(&range->p2.t, NULL);
        range->p2.count = 0;

        return 0;
}

static inline int timerange1_update(timerange1_t *range, uint64_t count) {
        _gettimeofday(&range->p2.t, NULL);
        range->p2.count = count;

        int64_t interval = _time_used(&range->p1.t, &range->p2.t);
        if (interval >= range->interval) {
                YASSERT(range->p2.count >= range->p1.count);

                DBUG("name %s interval %jd count %ju %ju speed %ju\n",
                      range->name, interval, range->p1.count, range->p2.count, range->speed);

                range->speed = (range->p2.count - range->p1.count) * 1000 * 1000 / interval;
                range->p1 = range->p2;
                return 1;
        }

        return 0;
}

/**
 * @brief 每一时刻对应两个指标计数器
 */
typedef struct {
        struct timeval t;
        uint64_t count1;
        uint64_t count2;
} timepoint2_t;

typedef struct {
        char name[MAX_NAME_LEN];
        int64_t interval;
        uint64_t speed;
        timepoint2_t p1;
        timepoint2_t p2;
} timerange2_t;

typedef int (*timerange2_func)(timerange2_t *range, int64_t interval, void *context);

static inline int timerange2_init(timerange2_t *range, const char *name, int64_t interval) {
        strcpy(range->name, name);
        range->interval = interval;
        range->speed = 0;

        _gettimeofday(&range->p1.t, NULL);
        range->p1.count1 = 0;
        range->p1.count2 = 0;

        _gettimeofday(&range->p2.t, NULL);
        range->p2.count1 = 0;
        range->p2.count2 = 0;

        return 0;
}

static inline int timerange2_update(timerange2_t *range, uint64_t count1, uint64_t count2,
                                    timerange2_func func, void *context) {
        _gettimeofday(&range->p2.t, NULL);
        range->p2.count1 = count1;
        range->p2.count2 = count2;

        int64_t interval = _time_used(&range->p1.t, &range->p2.t);
        if (interval >= range->interval) {
                YASSERT(range->p2.count1 >= range->p1.count1);
                YASSERT(range->p2.count2 >= range->p1.count2);

                DINFO("name %s interval %jd p1 %ju %ju p2 %ju %ju\n",
                      range->name,
                      interval,
                      range->p1.count1,
                      range->p1.count2,
                      range->p2.count1,
                      range->p2.count2);

                if (func) {
                        func(range, interval, context);
                }

                range->p1 = range->p2;
                return 1;
        }

        return 0;
}

#endif
